package com.best.testprogressbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ProgressBar;

/**
 * Created by FuKaiqiang on 2018-01-21.
 */

public class HorizontalProgressBarWithProgress extends ProgressBar {

    //声明自定义属性的变量，提供默认值，方便使用
    private static final int DEFAULT_TEXT_SIZE = 10; //sp
    private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
    private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;
    private static final int DEFAULT_HEIGHT_UNREACH = 2; //dp
    private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
    private static final int DEFAULT_HEIGHT_REACH = 2; //dp
    private static final int DEFAULT_TEXT_OFFSET = 10; //dp

    //声明变量
    protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
    protected int mTextColor = DEFAULT_TEXT_COLOR;
    protected int mUnReachColor = DEFAULT_COLOR_UNREACH;
    protected int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
    protected int mReachColor = DEFAULT_COLOR_REACH;
    protected int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
    protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
    protected Paint mPaint = new Paint();
    protected int mRealWidth; //当前控件的宽度减去它的Padding值，也就是真正的宽度；onMeasure赋值，onDraw使用

    //new控件的使用会调用一个参数的构造方法
    public HorizontalProgressBarWithProgress(Context context) {
        this(context, null);
    }

    //在布局中使用一般调用两个参数的构造方法并且进行自定义属性的获取
    public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(attrs);
    }

    /**
     * 获取自定义属性
     *
     * @param attrs
     */
    private void obtainStyledAttrs(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs,
                R.styleable.HorizontalProgressBarWithProgress);
        mTextSize = (int) typedArray.getDimension(R.styleable.HorizontalProgressBarWithProgress_progress_text_size,
                mTextSize);
        mTextColor = typedArray.getColor(R.styleable.HorizontalProgressBarWithProgress_progress_text_color,
                mTextColor);
        mTextOffset = (int) typedArray.getDimension(R.styleable.HorizontalProgressBarWithProgress_progress_text_offset,
                mTextOffset);
        mUnReachColor = typedArray.getColor(R.styleable.HorizontalProgressBarWithProgress_progress_unreach_color,
                mUnReachColor);
        mUnReachHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressBarWithProgress_progress_unreach_height,
                mUnReachHeight);
        mReachColor = typedArray.getColor(R.styleable.HorizontalProgressBarWithProgress_progress_reach_color,
                mReachColor);
        mReachHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressBarWithProgress_progress_reach_height,
                mReachHeight);
        typedArray.recycle();

        mPaint.setTextSize(mTextSize);
    }

    /**
     * 测量
     *
     * @param widthMeasureSpec  宽度的Spec
     * @param heightMeasureSpec 高度的Spec
     */
    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //利用MeasureSpec类获取widthMeasureSpec中宽度或高度的模式和值
        //根据progressbar的实际情况，用户在使用过程中肯定会给我一个宽度值，所以这里就不需要mode了，注销掉，直接拿值
//        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthVal = MeasureSpec.getSize(widthMeasureSpec);
        //widthMode与三种模式进行比较，做不同的处理
        int height = measureHeight(heightMeasureSpec);

        //宽和高都有了,setMeasuredDimension的意思是确定了view的宽和高
        setMeasuredDimension(widthVal, height);
        //赋值（实质上绘制的区域的宽度）
        mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
    }

    /**
     * 绘制三个部分 reachBar和Text和unreachBar
     *
     * @param canvas
     */
    @Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getPaddingLeft(), getHeight() / 2);
        //定义变量是否需要绘制
        boolean noNeedUnRech = false;
        //获取文本的宽度
        String text = getProgress() + "%";
        int textWidth = (int) mPaint.measureText(text);
        //整型转换为浮点型（当前的进度/最大的进度）
        float radio = getProgress() * 1.0f / getMax();
        //进度float值
        float progressX = radio * mRealWidth;
        if (progressX + textWidth> mRealWidth) {
            progressX = mRealWidth - textWidth;
            noNeedUnRech = true;
        }
        float endX = progressX-mTextOffset/2;
        if (endX > 0) {
            mPaint.setColor(mReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(0, 0, endX, 0, mPaint);
        }

        //draw text
        mPaint.setColor(mTextColor);
        int y = (int) (-(mPaint.descent() + mPaint.ascent() / 2));
        canvas.drawText(text, progressX,y,mPaint);

        //draw unreach bar
        if (!noNeedUnRech){
            //起始坐标
            float start = progressX+mTextOffset/2+textWidth;
            mPaint.setColor(mUnReachColor);
            mPaint.setStrokeWidth(mUnReachHeight);
            canvas.drawLine(start,0, mRealWidth,0,mPaint);
        }
        canvas.restore();
    }

    /**
     * 根据模式不同得到不同的height
     * 当EXACTLY时 result = size;当UNSPECIFIED时，result=测量之后的值；当AT_MOST时，取第一种模式和第二种模式下result的最小值
     *
     * @param heightMeasureSpec
     * @return
     */
    private int measureHeight(int heightMeasureSpec) {
        int result = 0;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        //  精确值模式
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        }
        //  AT_MOST和UNSPECIFIED两种模式需要自己去测量(分析：高度最大值是text高度决定的）
        else {
            //Paint 的高度  UNSPECIFIED模式下让我们自己测量
            int textHeight = (int) (mPaint.descent() +mPaint.ascent());
            //获取bar的高度 (上边距+下边距+mReachHeight或mUnReachHeight+textHeight的最大值）
            result = getPaddingTop() + getPaddingBottom() + Math.max(Math.max(mReachHeight, mUnReachHeight),
                    Math.abs(textHeight));
            //测量值不能超过给的那个size
            if (mode == MeasureSpec.AT_MOST) {
                //所以这里取最小值
                result = Math.min(result, size);
            }
        }
        return result;
    }

    //dp To px
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics());
    }

    //sp To px
    protected int sp2px(int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics());
    }

}
